﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using Db8.Data;

namespace Db8.DataAccess
{
    public partial class Db8Context : DbContext
    {
        public List<string> GetTopKeywords(string StickyFilter)
        {
            List<string> words = new List<string>();
            try
            {
                var popularQry = Keywords.OrderByDescending(k => k.ClaimCount)
                    .Select(k => new { ClaimCount = k.ClaimCount, Value = k.Value })
                    .Take(4)
                    .ToList();
                double topCount = popularQry.Max(k => k.ClaimCount);
                var popular = popularQry
                    .Select(k => new
                    {
                        Priority = Math.Sqrt(k.ClaimCount / topCount),
                        Value = k.Value
                    }).ToList();

                DateTime topTime = DateTime.UtcNow.AddHours(1);
                var recent = ClaimKeywords.OrderByDescending(ck => ck.Claim.ModifiedDt)
                    .Select(ck => new { ModifiedDt = ck.Claim.ModifiedDt, Value = ck.Keyword.Value })
                    .Take(40)
                    .ToList()
                    .Select(d => new
                    {
                        Priority = 1 / (Math.Sqrt((topTime - d.ModifiedDt).TotalHours)),
                        Value = d.Value
                    }).ToList();

                var prioritized = recent.Take(1).ToList();
                foreach (var a in recent.Skip(1))
                {
                    if (!prioritized.Any(p => p.Value == a.Value) && prioritized.Count < 4)
                        prioritized.Add(a);
                    if (prioritized.Count == 4)
                        break;
                }
                foreach (var a in popular)
                {
                    if (prioritized.Any(p => p.Value == a.Value))
                    {
                        var px = prioritized.FirstOrDefault(p => p.Value == a.Value);
                        if (px == null)
                            px = new { Priority = 0.0, Value = a.Value };

                        prioritized.RemoveAll(p => p.Value == a.Value);
                        prioritized.Add(new { Priority = px.Priority + a.Priority, Value = a.Value });
                    }
                    else
                    {
                        prioritized.Add(a);
                    }
                }

                words.AddRange(prioritized.OrderByDescending(p => p.Priority).Select(p => p.Value));

                if (!string.IsNullOrEmpty(StickyFilter))
                {
                    words.RemoveAll(s => s == StickyFilter);
                    words.Insert(0, StickyFilter);
                }
            }
            catch { }

            return words;
        }

        public List<Keyword> GetPopularKeywords(int count)
        {
            return Keywords.OrderByDescending(k => k.ClaimCount).Take(count).ToList();
        }
        public List<Keyword> GetRecentKeywords(int count)
        {
            List<Keyword> recent = new List<Keyword>();
            int skip = 0;
            int batchSize0 = count * 4;
            int batchSize = batchSize0;
            while (recent.Count < count)
            {
                var recentInstances = ClaimKeywords.OrderByDescending(ck => ck.Claim.ModifiedDt)
                    .Select(ck => new { ModifiedDt = ck.Claim.ModifiedDt, Keyword = ck.Keyword })
                    .Skip(skip)
                    .Take(batchSize)
                    .ToList();
                skip += batchSize;
                foreach (var keywordInstance in recentInstances)
                {
                    if (!recent.Any(kw => kw.Value == keywordInstance.Keyword.Value))
                        recent.Add(keywordInstance.Keyword);
                }
                if (recent.Count < count && batchSize == batchSize0)
                {
                    count = Math.Min(count, ClaimKeywords.Count());
                }
                batchSize = batchSize * 2;
            }
            return recent.Take(count).ToList();
        }

    }
}
